Texture2D baseTexture : register(t0);
SamplerState baseTextureSS : register(s0);

Texture2D DepthTexture : register(t1);

SamplerState ObjSamplerState
{
    Filter = MIN_MAG_MIP_POINT;
	AddressU = border;  
    AddressV = border;  
	borderColor = float4(0,0,0,0);  
	MaxLOD = 0;
	MinLOD = 0;
};

cbuffer cbPerObject// : register(c0)
{
    float4x4 VP;
	float4 FarPlane;
};

struct VS_IN
{
   float4 Position	: POSITION;
   half2 Size		: TEXCOORD0;
   half4 UV_AABB	: TEXCOORD1;
   half4 AddColor	: TEXCOORD2;
};

struct VS_OUT
{
	float4 Position : SV_POSITION;
	float2 Size		: TEXCOORD0;
	float4 UV_AABB	: TEXCOORD1;
	float4 AddColor	: TEXCOORD2;
};

struct GS_OUT
{
	float4 Position : SV_POSITION;
	float2 TexCoord	: TEXCOORD0;
	float4 AddColor	: TEXCOORD1;
};

#include "states.fx"

static const float2 offset[61] = {
float2( 0, 0), float2( 1, 0), float2( 1,-1), float2( 0,-1), float2(-1,-1), float2(-1, 0), float2(-1, 1), float2( 0, 1),
float2( 1, 1), float2( 2, 0), float2( 2,-1), float2( 2,-2), float2( 1,-2), float2( 0,-2), float2(-1, 2), float2(-2,-2),
float2(-2,-1), float2(-2, 0), float2(-2, 1), float2(-2, 2), float2(-1, 2), float2( 0, 2), float2( 1, 2), float2( 2, 2),
float2( 2, 1), float2( 3, 0), float2( 3,-1), float2( 1,-3), float2( 0,-3), float2(-1,-3), float2(-3,-1), float2(-3, 0),
float2(-3, 1), float2(-1,-3), float2( 0, 3), float2( 1, 3), float2( 3, 1), float2( 4, 0), float2( 4,-1), float2( 3,-2),
float2( 3,-3), float2(-2,-3), float2( 1,-4), float2( 0,-4), float2(-1,-4), float2(-2,-3), float2( 3,-3), float2(-3,-2),
float2(-4,-1), float2(-4, 0), float2(-4, 1), float2(-3, 2), float2(-3, 3), float2(-2, 3), float2(-1, 4), float2( 0, 4),
float2( 1, 4), float2( 2, 3), float2( 3, 3), float2( 3, 2), float2( 4, 1)};

static const int Nums[6] = {1, 4, 9, 25, 37, 61};

VS_OUT GSSprite_VS( VS_IN Input )
{
	float otn = float(SCREENX)/float(SCREENY);

	VS_OUT Output;
	Output.Position     = mul( Input.Position, VP );
	Output.Size = Input.Size*float2(1,otn)*1.33333;// / Output.Position.w;
	Output.UV_AABB = Input.UV_AABB;
	Output.AddColor = Input.AddColor;

	float Z = Output.Position.z;
	float2 ScrPos = Output.Position.xy / Output.Position.w;
	ScrPos.y*=-1;
	ScrPos = ScrPos*0.5 +0.5;
	

	float2 delta = 1/float2(SCREENX,SCREENY);

	int C = 4;

	float TOut = 0;
	for (int i =0; i < Nums[C]; i++)
	{
		float2 NewPos = ScrPos + delta*offset[i];
		if (NewPos.x >0 && NewPos.x<1 && NewPos.y> 0 && NewPos.y<1)
			TOut += DepthTexture.SampleLevel( ObjSamplerState,  NewPos, 0).x > Z/FarPlane.x;
	}

	TOut/=float(Nums[C]);
	Output.Size*= TOut;

	return Output;
}

[maxvertexcount(6)]  
void GSSprite_GS(point VS_OUT In[1], inout TriangleStream<GS_OUT> triStream)  
{  
	//if (length(In[0].Size) > 1)
	{
		GS_OUT p0 = (GS_OUT)0;
		GS_OUT p1 = (GS_OUT)0;
		GS_OUT p2 = (GS_OUT)0;
		GS_OUT p3 = (GS_OUT)0;

		p0.Position = In[0].Position + float4(In[0].Size*float2(1,1),0,0);
		p0.TexCoord = In[0].UV_AABB.zy;
		p0.AddColor = In[0].AddColor;
		p1.Position = In[0].Position + float4(In[0].Size*float2(-1,1),0,0);
		p1.TexCoord = In[0].UV_AABB.xy;
		p1.AddColor = In[0].AddColor;
		p2.Position = In[0].Position + float4(In[0].Size*float2(1,-1),0,0);
		p2.TexCoord = In[0].UV_AABB.zw;
		p2.AddColor = In[0].AddColor;
		p3.Position = In[0].Position + float4(In[0].Size*float2(-1,-1),0,0);
		p3.TexCoord = In[0].UV_AABB.xw;
		p3.AddColor = In[0].AddColor;

		triStream.Append(p0);
		triStream.Append(p1);
		triStream.Append(p2);
		triStream.RestartStrip();  

		triStream.Append(p1);
		triStream.Append(p2);
		triStream.Append(p3);
		triStream.RestartStrip();
	}
}

float4 GSSprite_PS( GS_OUT Input ) : SV_Target
{
	float4 fvBaseColor = baseTexture.Sample( baseTextureSS, Input.TexCoord.xy);
	float w = fvBaseColor.w*Input.AddColor.w;
	float tt = (fvBaseColor.x+fvBaseColor.y+fvBaseColor.z)/3;
	//fvBaseColor = sqrt((Input.AddColor*(1-tt) + float4(1,1,1,1)*tt)*tt);
	fvBaseColor = lerp(float4(fvBaseColor.xyz, 1), float4(Input.AddColor.xyz*tt, 1), 1-tt);//pow(1-tt, 1));
	fvBaseColor.w = w;

	return fvBaseColor*1.1;
}


technique10 T0
{
	pass P0
    {
        SetVertexShader   ( CompileShader( vs_4_0, GSSprite_VS() ) );
		SetGeometryShader ( CompileShader( gs_4_0, GSSprite_GS() ) );
        SetPixelShader    ( CompileShader( ps_4_0, GSSprite_PS() ) );
		SetRasterizerState(CullNone);
		SetDepthStencilState(DisableDepth, 0);
		SetBlendState ( AdditiveBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
    }
}